/**
 * https://www.tslang.cn/docs/handbook/basic-types.html
 * 为了让程序有价值，我们需要能够处理最简单的数据单元：数字，字符串，结构体，布尔值等。 
 * TypeScript支持与JavaScript几乎相同的数据类型，此外还提供了实用的枚举类型方便我们使用。
 * 
 */

let isDone: boolean = false;
isDone = true;

/**
 * 和JavaScript一样，TypeScript里的所有数字都是浮点数。 这些浮点数的类型是 number。 
 * 除了支持十进制和十六进制字面量，TypeScript还支持ECMAScript 2015中引入的二进制和八进制字面量。
 */
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;

/**
 * JavaScript程序的另一项基本操作是处理网页或服务器端的文本数据。 像其它语言里一样，
 * 我们使用 string表示文本数据类型。 和JavaScript一样，可以使用双引号（ "）或单引号（'）表示字符串。
 */

let personName: string = "bob";
personName = "smith";

/**
 * 你还可以使用模版字符串，它可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围（ `），
 * 并且以${ expr }这种形式嵌入表达式
 */

let anotherName: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${anotherName}.

I'll be ${ age + 1 } years old next month.`;

/**
 * TypeScript像JavaScript一样可以操作数组元素。 有两种方式可以定义数组。 第一种，可以在元素类型后面接上 []，表示由此类型元素组成的一个数组：
 */
let list1: number[] = [1,2,3];

/**
 * 第二种方式是使用数组泛型，Array<元素类型>
 */
let list2: Array<number> = [1, 2, 3];

/**
 * 元组类型允许表示一个已知元素数量和类型的数组，各元素的类型不必相同。 比如，你可以定义一对值分别为 string和number类型的元组。
 */

let xTuple: [string, number];
xTuple = ['hello', 10];

xTuple[2] = 100;
xTuple[3] = "world";

/**
 * enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样，使用枚举类型可以为一组数值赋予友好的名字。
 */
enum Color {Red, Green, Blue}
let c: Color = Color.Green;

enum Color2 {Red=1, Green, Blue}
enum Color3 { Red = 1, Green=2, Blue=4 }

let colorName: string = Color[2];
console.log('colorName: ', colorName);
console.log(Color3[3] == undefined );

/**
 * Any
 */
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean

let listAny : any[] = [1, true, "free"];
listAny[2] = 100;

/**
 * Void
 */
function warnUser():void{
    alert("This is my warning message");
}

/** 
 * 声明一个void类型的变量没有什么大用，因为你只能为它赋予undefined和null
 * 
*/
let unusable: void = undefined;
// unusable = 1; //Error

let u:undefined = undefined;
let n:null = null;

/**
 * Never
 */

// 返回never的函数必须存在无法达到的终点
function error(message: string):never{
    throw new Error(message);
}

// 推断的返回值类型为never
function fail(){
    return error("Something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop() : never {
    while (true){

    }
}

/**
 * 类型断言好比其它语言里的类型转换，但是不进行特殊的数据检查和解构。
 */
let someValue : any = "this is a string";

let strLength: number = (<string>someValue).length;

let someValue2 : any = "this is a string";
let strLength2 : number = (someValue2 as string).length;







